#include "GY_Scale.h"
#include "Graphics/GY_GraphicsReflection.h"
#include <QtMath>

GY_Scale::GY_Scale(const QString &guid, QGraphicsItem *parent)
    : GY_ContainerTransform(guid,this, parent)
{
    initializationPropertyInfo();
    this->setCenterPointF(m_PropertyInfoMap["Position"].propertyValue.toPointF());
    m_pSimpleGroup = new GY_SimpleGroup(QString("%1_SimpleGroup").arg(guid),this);
    this->addToGroup(m_pSimpleGroup);
    m_ChildrensMap.insert(m_pSimpleGroup->getGuid(),m_pSimpleGroup);
    updateDraw();
}

GY_Scale::~GY_Scale()
{

}

bool GY_Scale::addItem(GY_Object *pItem)
{
    //!移动容器回到原点
    m_pSimpleGroup->setPos(QPointF(0,0));
    m_pSimpleGroup->addItem(pItem);
    updateDraw();
    return true;
}

bool GY_Scale::removItem(const QString &guid)
{
    return m_pSimpleGroup->removItem(guid);
}

bool GY_Scale::removItem(const GY_Object *pItem)
{
    m_pSimpleGroup->removItem(pItem);
    this->GY_ContainerTransform::removItem(pItem);
    updateDraw();
    return true;
}

GY_Object *GY_Scale::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QVector<GY_Object *> childrens = m_pSimpleGroup->getOrderChildrens();
    int childrensSize = childrens.size();
    for(int i=0;i<childrensSize;i++) {
        ((GY_ContainerTransform*)pObj)->addItem(childrens[i]->copyItem());
    }

    QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
    while (iterProperty != m_PropertyInfoMap.end()) {
        if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
        }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
            ++iterProperty;
            continue;
        }else {
            pObj->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
        }
        ++iterProperty;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

void GY_Scale::initializationPropertyInfo()
{
    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_Scale::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    //位置
    GY_PropertyInfo positonPropertyInfo(this);
    positonPropertyInfo.propertyName="Position";
    positonPropertyInfo.propertyValue=QPointF(0,0);
    positonPropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    positonPropertyInfo.propertyType = PointPropertyType;
    positonPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_Scale::updatePosition;
    m_PropertyInfoMap.insert(positonPropertyInfo.propertyName,positonPropertyInfo);
    m_PropertyInfoMap[positonPropertyInfo.propertyName].setConnect();

    //是否显示
    GY_PropertyInfo isVisiblePropertyInfo(this);
    isVisiblePropertyInfo.propertyName="IsVisible";
    isVisiblePropertyInfo.propertyValue=true;
    isVisiblePropertyInfo.updateType = Update|OrdinaryAttributes;
    isVisiblePropertyInfo.propertyType = BoolPropertyType;
    isVisiblePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_Scale::updateIsVisible;
    m_PropertyInfoMap.insert(isVisiblePropertyInfo.propertyName,isVisiblePropertyInfo);
    m_PropertyInfoMap[isVisiblePropertyInfo.propertyName].setConnect();

    //Value
    GY_PropertyInfo ValuePropertyInfo(this);
    ValuePropertyInfo.propertyName="Value";
    ValuePropertyInfo.propertyValue=0;
    ValuePropertyInfo.updateType = Update|OrdinaryAttributes;
    ValuePropertyInfo.propertyType = FloatPropertyType;
    ValuePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_Scale::updateValue;
    m_PropertyInfoMap.insert(ValuePropertyInfo.propertyName,ValuePropertyInfo);
    m_PropertyInfoMap[ValuePropertyInfo.propertyName].setConnect();

    //StartValue
    GY_PropertyInfo StartValuePropertyInfo(this);
    StartValuePropertyInfo.propertyName="StartValue";
    StartValuePropertyInfo.propertyValue=0;
    StartValuePropertyInfo.updateType = Update|OrdinaryAttributes;
    StartValuePropertyInfo.propertyType = FloatPropertyType;
    StartValuePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_Scale::updateStartValue;
    m_PropertyInfoMap.insert(StartValuePropertyInfo.propertyName,StartValuePropertyInfo);
    m_PropertyInfoMap[StartValuePropertyInfo.propertyName].setConnect();

    //EndValue
    GY_PropertyInfo EndValuePropertyInfo(this);
    EndValuePropertyInfo.propertyName="EndValue";
    EndValuePropertyInfo.propertyValue=1;
    EndValuePropertyInfo.updateType = Update|OrdinaryAttributes;
    EndValuePropertyInfo.propertyType = FloatPropertyType;
    EndValuePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_Scale::updateEndValue;
    m_PropertyInfoMap.insert(EndValuePropertyInfo.propertyName,EndValuePropertyInfo);
    m_PropertyInfoMap[EndValuePropertyInfo.propertyName].setConnect();

    //编辑点
    GY_PropertyInfo pointPropertyInfo(this);
    pointPropertyInfo.propertyName="Point";
    pointPropertyInfo.propertyValue=QPointF(200,0);
    pointPropertyInfo.updateType = NotUpdate;
    pointPropertyInfo.propertyType = PointPropertyType;
    pointPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_Scale::updatePoint;
    m_PropertyInfoMap.insert(pointPropertyInfo.propertyName,pointPropertyInfo);
    m_PropertyInfoMap[pointPropertyInfo.propertyName].setConnect();

    //Motion位置
    GY_PropertyInfo MotionPropertyInfo(this);
    MotionPropertyInfo.propertyName="Motion";
    MotionPropertyInfo.propertyValue=QPointF(200,0);
    MotionPropertyInfo.updateType = Update|OrdinaryAttributes;
    MotionPropertyInfo.propertyType = PointPropertyType;
    MotionPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_Scale::updateMotion;
    m_PropertyInfoMap.insert(MotionPropertyInfo.propertyName,MotionPropertyInfo);
    m_PropertyInfoMap[MotionPropertyInfo.propertyName].setConnect();
}

void GY_Scale::updateDraw()
{
    //三个数值作为移动距离的比例
    float Value = m_PropertyInfoMap["Value"].propertyValue.toFloat();
    float StartValue = m_PropertyInfoMap["StartValue"].propertyValue.toFloat();
    float EndValue = m_PropertyInfoMap["EndValue"].propertyValue.toFloat();
    //移动总长度
    QPointF Motion = m_PropertyInfoMap["Motion"].propertyValue.toPointF();
    this->setEditPointF("Point",Motion);

    if(Value <= StartValue) {
        m_pSimpleGroup->setPos(QPointF(0,0));
    }else if(Value >= EndValue) {
        m_pSimpleGroup->setPos(Motion);
    }else {
        float propertion = (Value-StartValue)/(EndValue-StartValue);
        m_pSimpleGroup->setPos(propertion*Motion);
    }
}

bool GY_Scale::updatePosition(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    //setpos设置为父级坐标
    QPointF point = value.toPointF();
    if(this->parentItem()) {
        point = this->mapToParent(this->mapFromScene(value.toPointF()));
    }
    this->setPos(point);
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
    return true;
}

bool GY_Scale::updateIsVisible(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toBool();
    this->setVisible(value.toBool());
    return true;
}

bool GY_Scale::updateValue(const QString &name, const QVariant &value)
{
    if(!value.canConvert<float>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

bool GY_Scale::updateStartValue(const QString &name, const QVariant &value)
{
    if(!value.canConvert<float>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

bool GY_Scale::updateEndValue(const QString &name, const QVariant &value)
{
    if(!value.canConvert<float>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

bool GY_Scale::updatePoint(const QString &, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap["Motion"].propertyValue = this->mapFromScene(value.toPointF());
    updateDraw();
    return true;
}

bool GY_Scale::updateMotion(const QString &, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap["Motion"].propertyValue = value.toPointF();
    updateDraw();
    return true;
}



